#include <iostream>
#include <memory>

/*
auto_ptr是c++98中的，c++11中已经被摒弃了
c++11提供了unique_ptr和shared_ptr

double p * = new double;
会给p和double值分配内存空间，程序结束会删除p，但是double值还会被保存在内存中，不安全

auto_ptr<double> ap(new double)
*ap = 25.5;
智能指针是类似于指针的类对象，需要引入头文件<memory>
*/
class Report{
    private:
        std::string str;
    public:
        Report(const std::string s) : str(s){
            std::cout << "Object created !" << std::endl;
        }
        ~Report(){
            std::cout << "Object deleted !\n" ;
        }
        void comment() const {std::cout << str << std::endl;}

};
int main(){

    {
        std::auto_ptr<Report> ap (new Report("hello"));
        ap->comment();

    }

    {
        std::unique_ptr<Report> up(new Report("java"));
        up->comment();

    }
    {
        std::shared_ptr<Report> sp(new Report("ydsg"));
        sp->comment();
    }

    int a = 10;
    int *b = &a;
    int *c = &a;
    /*
    俩个常规指针指向同一个对象int a俩次，这是不能接受的，因为程序试图删除同一个对象俩次，需要避免这种问题
    那么如何解决这种问题呢？？
    1. 深复制，这样的话指针指向不同的对象，其中一个对象是另一个对象的副本
    2. 建立所有权，对于特定的对象，只能有一个智能指针指向它，可以转让所有权，auto_ptr和unique_ptr的策略
    3. 使用引用计数，指针过期时，计数-1，计数为0时，才删除，这是shared_ptr的策略
    */
   
   //下面展示一个auto_ptr的错误例子

    using namespace std;
    auto_ptr<string> films[3] = {
       auto_ptr<string> (new string("Jack !")),
       auto_ptr<string> (new string("qweasd !")),
       auto_ptr<string> (new string("popomart"))
    };
    auto_ptr<string> ap;
    ap = films[1];   //!!!将会导致segmentation fault,因为films[1]会失去所有权，所以films[1]是一个空指针，将会导致下面程序错误
    
    for(int i = 0; i < 5; i++){
        cout << *films[i] << endl;
    }

    //但是调用shared_ptr 程序可以正常运行，
    //unique_ptr也会崩溃，unique_ptr和auto_ptr都是采用所有权模型

    //但是unique_ptr为何要优于auto_ptr呢？？


    auto_ptr<string> p1 (new string("hello"));
    auto_ptr<string> p2;
    p2 = p1;  //p2接管了string对象的所有权，p1成为悬挂的空指针，如果后面程序继续用到，会报错

    unique_ptr<string> p3 (new string("hello"));
    unique_ptr<string> p4;
    p4 = p3; //在编译阶段就会报错，提高了安全等级
    
    return 0;
}

